#include "DbMysql.h"

namespace XIAOO{
    int DbMysql::query(std::string sql, Json::Value *root){
        this->_connect();

        this->_printSql(sql);

        //res??0??sql??ok
        int res = mysql_query(&this->conn, (char*)sql.c_str());
        if(res){
            std::cout << "query error:" << res << std::endl;
            printf("%s\n", mysql_error(&this->conn));
        }else{
            std::cout << "query ok:" << res << std::endl;
            MYSQL_RES *result;
            MYSQL_ROW sql_row;
            MYSQL_FIELD *field = 0;
            result = mysql_store_result(&this->conn);
            if(result){
                std::vector<std::string> columns;
                while((field = mysql_fetch_field(result))){
                    std::string columnName = field->name;
                    columns.push_back(columnName);
                }

                while( (sql_row = mysql_fetch_row(result)) ){
                //while???????????????????????????????????
                    Json::Value item;
                    for(int i = 0; i<columns.size(); i++){
                        item[columns[i]] = sql_row[i];
                    }
                    
                    root->append(item);
                }

            }else{
                std::cout << "empty result" << std::endl;
            }

            mysql_free_result(result);
        }

        return res;
    }

    int DbMysql::queryOne(std::string sql, Json::Value *root){
        this->_connect();

        this->_printSql(sql);

        //res??0??sql??ok
        int res = mysql_query(&this->conn, (char*)sql.c_str());
        if(res){
            std::cout << "query error:" << res << std::endl;
            printf("%s\n", mysql_error(&this->conn));
        }else{
            std::cout << "query ok:" << res << std::endl;
            MYSQL_RES *result;
            MYSQL_ROW sql_row;
            MYSQL_FIELD *field = 0;
            result = mysql_store_result(&this->conn);
            if(result){
                std::vector<std::string> columns;
                while((field = mysql_fetch_field(result))){
                    std::string columnName = field->name;
                    columns.push_back(columnName);
                }

                while( (sql_row = mysql_fetch_row(result)) ){
                    Json::Value temp;
                    for(int i = 0; i<columns.size(); i++){
                        temp[columns[i]] = sql_row[i];
                    }

                    *root = temp;
                    break;
                }

            }else{
                std::cout << "empty result" << std::endl;
            }

            mysql_free_result(result);
        }

        return res;
    }


    int DbMysql::insert(std::string sql, int *lastInsertId){
        this->_connect();

        this->_printSql(sql);

        int res = mysql_query(&conn, (char*)sql.c_str());
        if(res){
            printf("Insert failed (%s)\n", mysql_error(&conn));
        }else{
            std::cout << "insert success" << std::endl;
        }

        *lastInsertId = mysql_insert_id(&conn);
        return res;
    }

    void DbMysql::_connect(){
        XIAOO::Config config;
        Json::Value configData = config.readServerConfig();
        std::string host = configData["db"]["host"].asString();
        int port = configData["db"]["port"].asInt();
        std::string user = configData["db"]["user"].asString();
        std::string pw = configData["db"]["pw"].asString();
        std::string dbname = configData["db"]["db"].asString();
        std::string charset = configData["db"]["charset"].asString();
        
        if(this->isConn == true){
            return;
        }

        int res;
        mysql_init(&this->conn);

        std::cout << "【connect】" << std::endl;
        std::cout << configData << std::endl;
        std::cout << "host:" << host << std::endl;
        std::cout << "user:" << user << std::endl;
        std::cout << "pw:"  << pw << std::endl;
        std::cout << "dbname:" << dbname << std::endl;
        std::cout << "port:" << port << std::endl;
        std::cout << "【connect】" << std::endl;

        if(mysql_real_connect(&this->conn, host.c_str(), user.c_str(), pw.c_str(), dbname.c_str(), port, NULL, CLIENT_FOUND_ROWS)){
            this->isConn = true;
            mysql_set_character_set(&this->conn, charset.c_str());
            std::cout << "connect success" << std::endl;
        }else{
            std::cout << "connect error" << std::endl;
        }
        
    }

    void DbMysql::_printSql(std::string sql){
        if(this->isDebug){
            std::cout << "[*** sql begin ***]" << std::endl << sql << std::endl << "[*** sql end ***]" << std::endl;
        }
    }

    DbMysql::DbMysql(){
        this->isConn = false;
        this->isDebug = true;
    }

    DbMysql::~DbMysql(){
        mysql_close(&this->conn);
    }
}